/**************************************************************************************
 *  Copyright (c)  2010  Leszek Karcz, Changmin Bae.
 *  Permission is granted to copy, distribute and/or modify this document
 *  under the terms of the GNU Free Documentation License, Version 1.3
 *  or any later version published by the Free Software Foundation;
 *  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 *  A copy of the license is included in the section entitled "GNU
 *  Free Documentation License". 
 **************************************************************************************/
package data.tileables;

import data.LinkedList;
import data.Map;
import data.Player;

/**************************************************************************************
 * Author(s): Leszek Karcz, Changmin Bae
 * Base structure for all player buildings that can be put inside a tile
 **************************************************************************************/
public abstract class Structure extends Controllable
{
	private int imageFrames;
	private double completion;
	private double buildRate;
	private int workers;
	private int assignedWorkers=0;
	private int unassignedWorkers;
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz, Changmin Bae
	 * Structure constructor
	 **************************************************************************************/
	public Structure(int ID, int supertypeID, Player player, int workers)
	{
		super(ID, supertypeID, player);
		this.setType("Structure");
		this.setDisplayLevel(2);
		this.workers=workers;
		this.imageFrames=0;
		this.completion=0;
		unassignedWorkers = workers;
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz, Changmin Bae
	 * executes structures per tick instructions
	 **************************************************************************************/
	public void execute()
	{
		//building process will be handled by workers 
		if(!this.isFinished())
		{
			for(int i=0; i<this.workers; i++)
			{
			this.increaseCompletion();
			}
		}
		else
		{
			allocate();
			
			if(!missionQueue.isEmpty())
			{
				int flag = missionQueue.peekFirst().execute();
				if(flag == 1)
				{
					missionQueue.removeFirst();
				}
				else if(flag == 2)
				{
					System.out.println("flag = 2");
					if(missionQueue.getSize() > 1)
					{
						missionQueue.removeFirst();
					}
				}
			}
		}
	}
	
	
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * return the worker count
	 **************************************************************************************/
	public int getWorkerCount()
	{
		return this.workers;
	}
	
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * return the assigned worker count
	 **************************************************************************************/
	public int getAssignedWorkerCount()
	{
		return this.assignedWorkers;
	}
	
	public int getUnassignedWorkerCount()
	{
		return this.unassignedWorkers;
	}
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * change the worker count
	 **************************************************************************************/
	public void changeWorkerCount(int value)
	{
		this.workers+=value;
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * Return the stats of the controllable: HP/armor/Upkeep/etc.
	 **************************************************************************************/
	public String[] getStatsText()
	{
		int[] stats=this.getBaseStats();		
		return new String[]{"ID: "+this.getID(),
							"Health: "+(int)stats[0]+"/"+stats[1],
							"Armor: "+stats[2],
							"Offensive Damage: "+stats[3],
							"Defensive Damage: "+stats[4],
							"Vision: "+this.getVisionRadius(),
							"Upkeep: "+this.getUpkeep()[0]+" "+this.getUpkeep()[1]+" "+this.getUpkeep()[2],
							"State: "+this.getStateText(),
							"Workers: "+this.getWorkerCount(),
							"",
							"Mission: "+this.getCurrentMissionName()};
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * get image file name for the structure according to its level of completion
	 **************************************************************************************/
	public String getImage()
	{
		return super.getImage()+"_"+(int)(this.completion*(this.imageFrames-1)/100);
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * get highlight file name, icon file  name, health percentage
	 **************************************************************************************/
	public String[] getImageData(int playerID)
	{
		return new String[]{((this.getPlayerID()==playerID) && (this.equals(this.player.getSelected())) ? "pselected_struct_h" : "p"+this.getPlayerID()+"_struct_h"),this.getImage(),""+this.getHealthPercentage()};
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * get completion level
	 **************************************************************************************/
	public int getCompletion()
	{
		return (int)this.completion;
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * get max completion level
	 **************************************************************************************/
	public int getimageFrames()
	{
		return this.imageFrames;
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * returns whether building is finished
	 **************************************************************************************/
	public boolean isFinished()
	{
		return (this.completion==100);
	}

	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * increase completion level by one
	 **************************************************************************************/
	public void increaseCompletion()
	{
		this.changeHealth((this.getStats()[1]*this.buildRate/(100)));
		this.completion+=this.buildRate;
		if(this.completion>100)
		{
			this.completion=100;
		}
	}	
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * Return the state in text form
	 **************************************************************************************/
	public String getStateText()
	{
		if(!this.isFinished())
		{
				return "Building "+(int)(this.getCompletion())+"%";
		}
		else
		{
			if(this.getState()==0)
			{
				return "Power-down";
			}
			else
			{
				return "Active";
			}
		}
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * Set the stats of the building: imageFrames/buildRate/HP/armor/baseUpkeep/etc.
	 **************************************************************************************/
	protected void setStats(int imageFrames, double buildRate, int maxHealth, int armor, int offensiveDamage, int defensiveDamage, int visionRadius)
	{
		this.imageFrames=imageFrames;
		this.buildRate=buildRate;
		int health=0;
		super.setStats(health, maxHealth, armor, offensiveDamage, defensiveDamage, visionRadius);
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * Returns the vision radius of structure, if structure is unfinished the radius is 0
	 **************************************************************************************/
	public int getVisionRadius()
	{
		if(this.isFinished())
		{
		return super.getVisionRadius();
		}
		else
		{
			return 0;
		}
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * returns number of commands, 1 if the structure is not finished
	 **************************************************************************************/
	public int getNumberOfCommands()
	{
		if(this.isFinished())
		{
			return super.getNumberOfCommands();
		}
		else
		{
			return 1;
		}
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * returns selected command, 0 if the structure is not finished
	 **************************************************************************************/
	public int getSelectedCommand()
	{
		if(this.isFinished())
		{
			return super.getSelectedCommand();
		}
		else
		{
			return 0;
		}
	}
	
	
	/**************************************************************************************
	 * Author(s): Eric Martin-Taylor
	 * Adds Workers to the structure
	 * 		True = successful
	 * 		False = fail
	 **************************************************************************************/
	public boolean addWorkers(int amount){	
		workers+=amount;
		return true;
	}

	
	/**************************************************************************************
	 * Author(s): Eric Martin-Taylor	 
	 * Removes workers from the structure.
	 * 		The number returned is the amount of workers removed
	 **************************************************************************************/
	public int removeWorkers(int amount){
		
		int temp = 0;
		if(workers-amount < 0){
			temp = workers;
			workers = 0;
			return temp;
		}
			
		workers -= amount;
		return amount;
	
	}
	
	/**************************************************************************************
	 * Author(s): Eric Martin-Taylor	 
	 * Kilss the base and gives the player back the workers
	 **************************************************************************************/
	public void die()
	{ 
		super.die();
		this.player.changeWorkerCount(-this.getWorkerCount());
	}
	
	public int []getUpkeep(){
		int [] upkeep = super.getUpkeep();
		
		upkeep[FOOD] *= workers;
		
		return upkeep;
	}
}
